/* 泛型:类型参数化 */

//泛型函数：使用<T>声明泛型类型参数（紧跟函数名），后续可用T表示该类型
function fun<T>(value: T): T {
    return value;
}

//1.显式指定类型调用
let str = fun<string>('zx');
console.log("字符串类型调用：", str);

let num = fun<number>(45);
console.log("数字类型调用：", num, "\n");


//2.ts自动推断类型
let str1 = fun('tx');
console.log("字符串类型调用：", str1);

let num1 = fun(74);
console.log("数字类型调用：", num1, "\n");


//两个参数
function fun1<T, Y>(a: T, b: Y): [T, Y] {
    return [a, b];
}

let res = fun1<string, number>('Mary', 36);
console.log("双类型调用：", res);
let res1 = fun1(2, 'Make');
console.log("双类型调用：", res1, "\n");

//单类型对象泛型
type Obj<T> = {
    value: T
}

//对象参数类型是泛型后，在实际应用中要明确泛型类型
let obj1: Obj<string> = {
    value: "Make"
}

console.log("对象单参数泛型调用：", obj1);

//多类型对象泛型
type Obj1<T, U, V> = {
    value: T;
    count: U;
    active: V
}

let obj2: Obj1<string, number, boolean> = {
    value: "Make",
    count: 10,
    active: true
}

console.log("对象多参数泛型调用：", obj2, "\n");

// 接口泛型同上，以下是接口演示（各个泛型T在各自作用域中，T代表不同）
interface Inter<T>{
    id:number,
    fun:T
}

type Fun<T,U> = (a:T, b: U) => T;

let inter1: Inter<Fun<string,number>> = {
    id: 1,
    fun: (a:string, b: number) => a + b.toString()
};

console.log("接口泛型调用：", inter1);
console.log("接口add函数调用结果： ",inter1.fun('zf',4));


//TS内置了几个类型工具
interface Res{
    status:number,
    data:string
}
//让属性可选
type rx =  Partial<Res>
let rx1:rx = {
    status:23,
} 